package com.xiaoma.lib.log;

import android.annotation.SuppressLint;
import android.content.Context;
import android.text.TextUtils;

import com.xiaoma.seres.lib.log.ILog;
import com.xiaoma.lib.log.impl.AndroidLog;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.Arrays;


public class KLog {
    private static final String TAG = "KLog";
    private static final String XM_TAG = "XM";
    private static final int JSON_INDENT = 2;
    private final static ILog sLog = new AndroidLog();

    public static void init(Context context, String uid) {
        sLog.init(context, uid);
    }

    private static boolean isShowLog() {
        return sLog.isShowLog();
    }

    public static boolean isLowLevelLogPrintEnable() {
        return sLog.isLowLevelLogPrintEnable();
    }

    public static void setLowLevelLogPrintEnable(boolean lowLevelLogPrintEnable) {
        sLog.setLowLevelLogPrintEnable(lowLevelLogPrintEnable);
        e(TAG, "setShowLog lowLevelLogPrintEnable = " + lowLevelLogPrintEnable);
    }

    public static void d(@Nullable Object message) {
        if (isLowLevelLogPrintEnable()) {
            sLog.d(XM_TAG, toString(message));
        }
    }

    @SuppressLint("XMLog Tag为字符串或表达式返回值")
    public static void d(@NotNull String tag, @Nullable Object message) {
        if (isLowLevelLogPrintEnable()) {
            sLog.d(tag, toString(message));
        }
    }

    @SuppressLint("XMLog Tag为字符串或表达式返回值")
    public static void d(@NotNull String tag, @NotNull String message, @Nullable Throwable tr) {
        if (isLowLevelLogPrintEnable()) {
            sLog.d(tag, message, tr);
        }
    }

    public static void e(@NotNull String message) {
        if (isShowLog()) {
            sLog.e(XM_TAG, message);
        }
    }

    @SuppressLint("XMLog Tag为字符串或表达式返回值")
    public static void e(@NotNull String tag, @NotNull String message) {
        if (isShowLog()) {
            sLog.e(tag, message);
        }
    }

    @SuppressLint("XMLog Tag为字符串或表达式返回值")
    public static void e(@NotNull String tag, @NotNull String message, @Nullable Throwable tr) {
        if (isShowLog()) {
            sLog.e(tag, message, tr);
        }
    }

    public static void i(@NotNull String message) {
        if (isLowLevelLogPrintEnable()) {
            sLog.i(XM_TAG, message);
        }
    }

    @SuppressLint("XMLog Tag为字符串或表达式返回值")
    public static void i(@NotNull String tag, @NotNull String message) {
        if (isLowLevelLogPrintEnable()) {
            sLog.i(tag, message);
        }
    }

    @SuppressLint("XMLog Tag为字符串或表达式返回值")
    public static void i(@NotNull String tag, @NotNull String message, @Nullable Throwable tr) {
        if (isLowLevelLogPrintEnable()) {
            sLog.i(tag, message, tr);
        }
    }


    public static void v(@NotNull String message) {
        if (isLowLevelLogPrintEnable()) {
            sLog.v(XM_TAG, message);
        }
    }

    @SuppressLint("XMLog Tag为字符串或表达式返回值")
    public static void v(@NotNull String tag, @NotNull String message) {
        if (isLowLevelLogPrintEnable()) {
            sLog.v(tag, message);
        }
    }

    @SuppressLint("XMLog Tag为字符串或表达式返回值")
    public static void v(@NotNull String tag, @NotNull String message, @Nullable Throwable tr) {
        if (isLowLevelLogPrintEnable()) {
            sLog.v(tag, message, tr);
        }
    }

    public static void w(@NotNull String message) {
        if (isShowLog()) {
            sLog.w(XM_TAG, message);
        }
    }

    @SuppressLint("XMLog Tag为字符串或表达式返回值")
    public static void w(@NotNull String tag, @NotNull String message) {
        if (isShowLog()) {
            sLog.w(tag, message);
        }
    }

    @SuppressLint("XMLog Tag为字符串或表达式返回值")
    public static void w(@NotNull String tag, @NotNull String message, @Nullable Throwable tr) {
        if (isShowLog()) {
            sLog.w(tag, message, tr);
        }
    }

    /**
     * Formats the given json content and print it
     */
    public static void json(@Nullable String json) {
        if (!isShowLog()) {
            return;
        }
        handleJson(json);
    }

    @SuppressLint("XMLog Tag为字符串或表达式返回值")
    public static void json(@Nullable String tag, @Nullable String json) {
        if (isShowLog()) {
            handleJson(tag, json);
        }
    }

    private static void handleJson(String json) {
        if (TextUtils.isEmpty(json)) {
            d("Empty/Null json content");
            return;
        }
        try {
            json = json.trim();
            if (json.startsWith("{")) {
                JSONObject jsonObject = new JSONObject(json);
                String message = jsonObject.toString(JSON_INDENT);
                d(message);
                return;
            }
            if (json.startsWith("[")) {
                JSONArray jsonArray = new JSONArray(json);
                String message = jsonArray.toString(JSON_INDENT);
                d(message);
                return;
            }
            e("Invalid Json");
        } catch (JSONException e) {
            e("Invalid Json");
        }
    }

    @SuppressLint("XMLog Tag为字符串或表达式返回值")
    private static void handleJson(String tag, String json) {
        if (TextUtils.isEmpty(json)) {
            d(tag, "Empty/Null json content");
            return;
        }
        try {
            json = json.trim();
            if (json.startsWith("{")) {
                JSONObject jsonObject = new JSONObject(json);
                String message = jsonObject.toString(JSON_INDENT);
                d(tag, message);
                return;
            }
            if (json.startsWith("[")) {
                JSONArray jsonArray = new JSONArray(json);
                String message = jsonArray.toString(JSON_INDENT);
                d(tag, message);
                return;
            }
            e(tag, "Invalid Json");
        } catch (JSONException e) {
            e(tag, "Invalid Json");
        }
    }

    public static String toString(Object object) {
        if (object == null) {
            return "null";
        }
        if (!object.getClass().isArray()) {
            return object.toString();
        }
        if (object instanceof boolean[]) {
            return Arrays.toString((boolean[]) object);
        }
        if (object instanceof byte[]) {
            return Arrays.toString((byte[]) object);
        }
        if (object instanceof char[]) {
            return Arrays.toString((char[]) object);
        }
        if (object instanceof short[]) {
            return Arrays.toString((short[]) object);
        }
        if (object instanceof int[]) {
            return Arrays.toString((int[]) object);
        }
        if (object instanceof long[]) {
            return Arrays.toString((long[]) object);
        }
        if (object instanceof float[]) {
            return Arrays.toString((float[]) object);
        }
        if (object instanceof double[]) {
            return Arrays.toString((double[]) object);
        }
        if (object instanceof Object[]) {
            return Arrays.deepToString((Object[]) object);
        }
        return "Couldn't find a correct type for the object";
    }

//    public static Deferred<Boolean> pushCommand(String message) {
//        return XMLog.onPushCommandAsync(message);
//    }
}
